#include "EpilForNumberStatementParser.h"
#include "EpilExpressionParser.h"
#include "EpilChunkParser.h"
#include "EpilParserException.h"
#include "EpilPointerHelper.h"


EpilForNumberStatementParser::EpilForNumberStatementParser( EpilTokenStream & tokens )
: EpilSyntaxParserBase( tokens )
{
}


void EpilForNumberStatementParser::Parse()
{
	// fornum -> NAME = begin, end [, step] DO block END
	m_statement = new EpilForNumberStatementCode( this->GetTokens().GetPreviousToken().location );

	// NAME
	if( this->GetTokens().GetCurrentToken().type != ETT_Identifier )
	{
		EpilPointerHelper::SafeDelete( m_statement );
		throw EpilParserException( t("Identifier expected."), this->GetTokens().GetCurrentToken().location );
	}
	m_statement->SetVariable( this->GetTokens().GetCurrentToken().text );
	this->GetTokens().MoveToNext();

	// =
	if( this->GetTokens().GetCurrentToken().type != ETT_OpAssign )
	{
		EpilPointerHelper::SafeDelete( m_statement );
		throw EpilParserException( t("\'=\' expected."), this->GetTokens().GetCurrentToken().location );
	}
	this->GetTokens().MoveToNext();

	// begin
	EpilExpressionParser beginParser( this->GetTokens() );
	try
	{
		beginParser.Parse();
	}
	catch( ... )
	{
		EpilPointerHelper::SafeDelete( m_statement );
		throw;
	}
	m_statement->SetBegin( beginParser.GetExpression() );

	// ,
	if( this->GetTokens().GetCurrentToken().type != ETT_OpComma )
	{
		EpilPointerHelper::SafeDelete( m_statement );
		throw EpilParserException( t("\',\' expected."), this->GetTokens().GetCurrentToken().location );
	}
	this->GetTokens().MoveToNext();

	// end
	EpilExpressionParser endParser( this->GetTokens() );
	endParser.Parse();
	m_statement->SetEnd( endParser.GetExpression() );

	// ,
	if( this->GetTokens().GetCurrentToken().type == ETT_OpComma )
	{
		this->GetTokens().MoveToNext();

		// step
		EpilExpressionParser stepParser( this->GetTokens() );
		stepParser.Parse();
		m_statement->SetStep( stepParser.GetExpression() );
	}
	else
	{
		m_statement->SetStep( NULL );
	}

	// DO
	if( this->GetTokens().GetCurrentToken().type != ETT_KwDo )
	{
		EpilPointerHelper::SafeDelete( m_statement );
		throw EpilParserException( t("\'do\' expected."), this->GetTokens().GetCurrentToken().location );
	}
	this->GetTokens().MoveToNext();

	// block
	EpilChunkParser chunkParser( this->GetTokens() );
	chunkParser.Parse();
	m_statement->SetBlock( chunkParser.GetChunk() );

	// DO
	if( this->GetTokens().GetCurrentToken().type != ETT_KwEnd )
	{
		EpilPointerHelper::SafeDelete( m_statement );
		throw EpilParserException( t("\'end\' expected."), this->GetTokens().GetCurrentToken().location );
	}
	this->GetTokens().MoveToNext();
}